use core::result::Result;

#[derive(Debug, Clone)]
pub struct Url<'a> {
    pub schema: &'a str,
    pub host: &'a str,
    pub port: Option<u16>,
    pub uri: &'a str,
}

impl<'a> Url<'a> {
    pub fn parse(s: &'a str) -> Result<Self, &'static str> {
        let mut my = Self {
            schema: "",
            host: "",
            port: None,
            uri: "/",
        };
        let s1 = s.trim();
        let pos = s1.find("://").ok_or("no schema")?;
        my.schema = &s1[..pos];
        let s1 = &s1[pos + 3..];
        if let Some(pos) = s1.find("/") {
            my.host = &s1[..pos];
            my.uri = &s1[pos..];
        } else {
            my.host = &s1[..];
        }
        if let Some(pos) = my.host.find(":") {
            my.port = Some(
                my.host[pos + 1..]
                    .parse::<u16>()
                    .map_err(|_e| "invalid port")?,
            );
            my.host = &my.host[..pos];
        }
        Ok(my)
    }
}

#[cfg(test)]
pub mod test {
    use crate::url::Url;

    #[test]
    fn test_uri() {
        let normal = "ws://localhost/v1/a/b?a=1&b=2";
        let normal_url = Url::parse(normal);
        assert!(normal_url.is_ok());
        let normal_url = normal_url.unwrap();
        assert_eq!(normal_url.schema, "ws");
        assert_eq!(normal_url.host, "localhost");
        assert_eq!(normal_url.port, None);
        assert_eq!(normal_url.uri, "/v1/a/b?a=1&b=2");

        let normal = "http://localhost:80/v1/a/b?a=1&b=2";
        let normal_url = Url::parse(normal);
        assert!(normal_url.is_ok());
        let normal_url = normal_url.unwrap();
        assert_eq!(normal_url.schema, "http");
        assert_eq!(normal_url.host, "localhost");
        assert_eq!(normal_url.port, Some(80));
        assert_eq!(normal_url.uri, "/v1/a/b?a=1&b=2");

        let normal = "https://localhost:80";
        let normal_url = Url::parse(normal);
        assert!(normal_url.is_ok());
        let normal_url = normal_url.unwrap();
        assert_eq!(normal_url.schema, "https");
        assert_eq!(normal_url.host, "localhost");
        assert_eq!(normal_url.port, Some(80));
        assert_eq!(normal_url.uri, "/");
    }
}
